package app;

import java.io.File;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.SourceDataLine;

public class PlayerCore {

	private AudioInputStream din;
	private AudioInputStream audioStream;
	private AudioFormat decodedFormat;
	private SourceDataLine line;
	private int volume = 50;

	public PlayerCore() {
	}

	public void open(File file) {
		try {
			audioStream = AudioSystem.getAudioInputStream(file);
			AudioFormat baseFormat = audioStream.getFormat();
			decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
					baseFormat.getSampleRate(), 16, baseFormat.getChannels(),
					baseFormat.getChannels() * 2, baseFormat.getSampleRate(),
					false);
			din = AudioSystem.getAudioInputStream(decodedFormat, audioStream);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void play() {
		try {
			byte[] data = new byte[16384];
			line = getLine(decodedFormat);

			if (line != null) {
				// Start
				line.start();
				// set volume level
				setVolume(volume);
				int nBytesRead = 0;
				while (nBytesRead != -1) {
					nBytesRead = din.read(data, 0, data.length);
					if (nBytesRead != -1) {
						line.write(data, 0, nBytesRead);
					}

				}

				// Playing Finished
				System.out.println("Song playback finished");
				stop();
			}
		} catch (Exception e) {
			
			System.err.println("Error while playing song");
			System.err.println(e.getMessage());
		}

	}

	private SourceDataLine getLine(AudioFormat audioFormat) {
		SourceDataLine res = null;
		try {

			DataLine.Info info = new DataLine.Info(SourceDataLine.class,
					audioFormat);
			res = (SourceDataLine) AudioSystem.getLine(info);
			res.open(audioFormat);
		} catch (Exception e) {
			System.err.println("Error while opening song");
		}
		return res;
	}

	public void stop() {
		try {
			line.stop();
			line.close();
			din.close();
			audioStream.close();
		} catch (Exception e) {
			System.err.println("Error while stopping playback.");
		}
	}

	public void pause() {
		line.drain();
	}

	public void adjustVolume(int offset) {
		int value = volume + offset;
		if (value < 0)
			value = 0;
		if (value > 100)
			value = 100;
		volume = value;
		setVolume(volume);
	}

	public void setVolume(int percent) {
		volume = percent;
		FloatControl gainControl;
		if (line == null) {
			return;
		}
		
		gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN);
		float maximum = gainControl.getMaximum();
		float minimum = gainControl.getMinimum();
		float range = Math.abs(maximum - minimum);
		float value = minimum + ((float) (percent * 100)) / range;

		gainControl.setValue(value);
	}

	public int getVolume() {
		return ((int) volume);
	}

	public int getProgress() {
		if (line == null || audioStream == null)
			return 0;

		// na sekundy
		return ((int) line.getMicrosecondPosition() / 1000000);
	}

}
